#ifndef __THREAD_HPP__
#define __THREAD_HPP__

#include <iostream>
#include <cstdio>
#include <string>
#include <pthread.h>
#include <functional>
#include <unistd.h>

namespace ThreadModule
{
	static int thread_count = 1;

	using func_t = std::function<void()>;

	class Thread
	{
	public:
		Thread(func_t func) : _tid(0),
							  _isdetach(false),
							  _isrunning(false),
							  _ret(0),
							  _func(func)
		{
			_name = "Thread-" + std::to_string(thread_count++);
		}

		void EnableDetach()
		{
			_isdetach = true;
		}

		void EnableRunning()
		{
			_isrunning = true;
		}

		void Detach()
		{
			if (_isdetach)
				return;

			int n = pthread_detach(_tid);
			if (n != 0)
			{
				std::cerr << "Error detaching thread: " << n << std::endl;
			}
			std::cout << "线程已分离" << std::endl;

			EnableDetach();
		}

		bool Start()
		{
			if (_isrunning)
				return true;

			int n = pthread_create(&_tid, nullptr, routine, this);
			if (n != 0)
			{
				std::cerr << "Error creating thread: " << n << std::endl;
				return false;
			}

			EnableRunning();

			if (_isdetach)
			{
				Detach();
			}

			return true;
		}

		void Join()
		{
			if (_isdetach)
				return;

			int n = pthread_join(_tid, nullptr);
			if (n != 0)
			{
				//std::cerr << "Error joining thread: " << n << std::endl;
			}

			//std::cout << "join success" << std::endl;
		}

		void Stop()
		{
			if (!_isrunning)
				return;

			if (!_isdetach)
			{
				std::cout<<"线程未分离，需要等待"<<std::endl;
				Join();
				std::cout<<"等待完成"<<std::endl;
			}
			else
			{
				int n = pthread_cancel(_tid);
				if (n != 0)
				{
					std::cerr << "Error canceling thread: " << n << std::endl;
				}
				else{
					std::cout<<"已成功关闭分离的线程"<<std::endl;
				}
			}

			_isrunning = false;
		}

		std::string GetName() const{
			return _name;
		}

		pthread_t Id() const {
			return _tid;
		}

		~Thread() {}

	private:
		pthread_t _tid;
		std::string _name;
		bool _isdetach;
		bool _isrunning;
		int _ret;
		func_t _func;


		static void *routine(void *args)
		{
			Thread *self = static_cast<Thread *>(args);
			if (self && self->_func)
			{
				self->_func();
			}

			return nullptr;
		}
	};
}

#endif